package com.jrzh.mvc.service.sys.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.Serializable;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jrzh.common.cache.Cache;
import com.jrzh.common.cache.CacheManager;
import com.jrzh.common.exception.ProjectException;
import com.jrzh.common.tools.CollectionTools;
import com.jrzh.common.tools.JsonTools;
import com.jrzh.common.utils.ReflectUtils;
import com.jrzh.config.ProjectConfigration;
import com.jrzh.db.data.execute.sys.ExecuteI18n;
import com.jrzh.framework.base.convert.BaseConvertI;
import com.jrzh.framework.base.repository.BaseRepository;
import com.jrzh.framework.base.service.impl.BaseServiceImpl;
import com.jrzh.framework.bean.SessionUser;
import com.jrzh.framework.contants.GeneralConstant;
import com.jrzh.framework.execute.ExecuteBase;
import com.jrzh.mvc.convert.sys.I18nConvert;
import com.jrzh.mvc.model.sys.I18nModel;
import com.jrzh.mvc.repository.sys.I18nRepository;
import com.jrzh.mvc.search.sys.I18nSearch;
import com.jrzh.mvc.service.sys.I18nServiceI;
import com.jrzh.mvc.view.sys.I18nView;

@Service("i18nService")
public class I18nServiceImpl extends BaseServiceImpl<I18nModel, I18nSearch, I18nView> implements I18nServiceI{
	
	@Autowired
	private I18nRepository i18nRepository;
	
	@Autowired
	private I18nConvert i18nConvert;
	
	@Autowired
	private ProjectConfigration projectConfigration;

	@Override
	public BaseRepository<I18nModel, Serializable> getDao() {
		return i18nRepository;
	}

	@Override
	public BaseConvertI<I18nModel, I18nView> getConvert() {
		return i18nConvert;
	}

	@Override
	public void saveInit(String project) throws ProjectException {
		log.info("###########同步"+ project  +"模块 国际化表数据 Begin");
		String package_url = "com/jrzh/db/data/json/" + project + "/i18n";
		URL url = ExecuteI18n.class.getResource("/" + package_url);
		File file = null;
		Map<String, List<String>>  i18nFileMap = new HashMap<String, List<String>>();
		if(null == url) {
			package_url = "java/"+package_url;
			url = ExecuteI18n.class.getResource("/" + package_url);
			file = new File(url.getFile());
			if(!file.exists()) {
				try {
					Enumeration<URL> urls = Thread.currentThread().getContextClassLoader().getResources(package_url);
					while (urls.hasMoreElements()) {
						URL _url = urls.nextElement();
			            if (_url != null) {
			                String protocol = _url.getProtocol();
			                if(StringUtils.equals("jar", protocol)) {
			                	 JarURLConnection jarURLConnection = (JarURLConnection) _url.openConnection();
			                    JarFile jarFile = jarURLConnection.getJarFile();
			                    Enumeration<JarEntry> jarEntries = jarFile.entries();
			                    while (jarEntries.hasMoreElements()) {
			                        JarEntry jarEntry = jarEntries.nextElement();
			                        String jarEntryName = jarEntry.getName();
			                        if(StringUtils.contains(jarEntryName, "/i18n/") && jarEntryName.endsWith(".json")) {
			                        	String lan = jarEntryName.split("/i18n/")[1].split("\\/")[0];
			                        	//log.info("解析jar，获得语言包:[" + lan + "]" );
			                        	List<String> i18nFiles = i18nFileMap.get(lan);
			                        	if(null == i18nFiles) i18nFiles = new ArrayList<String>();
			                        	i18nFiles.add(jarEntryName);
			                        	i18nFileMap.put(lan, i18nFiles);
			                        }
			                    }
			                }
			            }
			       }
				} catch (Exception e) {
					log.error(e.getMessage());
					throw new ProjectException("加载jar包 模块i18n加载失败，文件找不到");
				}
			}
		}else {
			file = new File(url.getFile());
			if(!file.exists()) {
				//log.info("[" + project + "] [" + file.getPath() +"]模块i18n加载失败，文件找不到");
				throw new ProjectException("[" +  file.getPath()+ "] 模块i18n加载失败，文件找不到");
			}
		}
		if(null != file && file.exists()) {
			File[] i18nDirs = file.listFiles();
			for(File i18nDir : i18nDirs) {
				String lan = i18nDir.getName();
				File[] i18nFileArray = i18nDir.listFiles();
				for(File i18nFile : i18nFileArray) {
					List<String> i18nFiles = i18nFileMap.get(lan);
                	if(null == i18nFiles) i18nFiles = new ArrayList<String>();
                	i18nFiles.add(i18nFile.getPath());
                	i18nFileMap.put(lan, i18nFiles);
				}
			}
		}
		Set<String> inCodes = new HashSet<String>();
		for(Entry<String, List<String>> entry : i18nFileMap.entrySet()) {
			String lan = entry.getKey();
			List<String> i18nFiles = entry.getValue();
			//log.info("加载[" + project + "]模块[" + lan + "]语言 Begin");
			for(String i18nFileUrl : i18nFiles) {
				//log.info("加载[" + project + "]模块[" + lan + "]语言文件[" + i18nFileUrl + "] Begin");
				JSONArray array = null;
				try {
					//log.info("加载本地...................");
					array = JsonTools.getFromFile(new FileInputStream(i18nFileUrl));
				} catch (Exception e) {
					//log.info("加载本地异常，匹配加载Jar...................");
					try {
						
						array = JsonTools.getFromFile(ExecuteBase.class.getClassLoader().getResourceAsStream(i18nFileUrl));
					} catch (Exception e2) {
						//log.info("加载Jar异常，无法初始化I18n...................");
						throw new ProjectException("加载Jar异常，无法初始化I18n...................");
					}
				}
				if(null != array && array.size() > 0){
					for(int i = 0; i < array.size(); i ++){
						JSONObject jsonObject = array.getJSONObject(i);
						String code =jsonObject.getString("code");
						inCodes.add(code);
						I18nModel model = new I18nModel();
						ReflectUtils.setValue(lan, model, jsonObject.getString("value"));
						model.setCode(code);
						model.setModel(code.split("\\.")[0]);
						I18nModel dbm = this.findByField("code", model.getCode());
						if(null == dbm){
							//log.info("######新增" + model.getCode());
							this.add(model, SessionUser.getSystemUser());
						}else{
							if(!equals(dbm, model, lan)){
								//log.info("######编辑" + model.getCode());
								ReflectUtils.setValue(lan, dbm, jsonObject.getString("value"));
								this.edit(dbm, SessionUser.getSystemUser());
							}
						}
					}
				}
				//log.info("加载[" + project + "]模块[" + lan + "]语言文件[" + i18nFileUrl + "] End");
			}
			//log.info("加载[" + project + "]模块[" + lan + "]语言 End");
		}
		//处理删除的数据
//		List<I18nModel> list = this.listNotInByField("code", inCodes.toArray());
//		if(CollectionTools.isNotBlank(list)){
//			for(I18nModel m : list){
//				this.delete(m.getId(), SessionUser.getSystemUser());
//			}
//		}
		log.info("###########同步"+project+"模块 国际化数据 End");
	}
	
	private Boolean equals(I18nModel source, I18nModel target, String lan) throws ProjectException {
		return StringUtils.equals(source.getCode(), target.getCode()) &&
				   StringUtils.equals(source.getModel(), target.getModel()) &&
				   StringUtils.equals(ReflectUtils.getValue(lan, source) + "", ReflectUtils.getValue(lan, target) + "") ;
	}

	@Override
	public void initCache() throws ProjectException {
		log.info("加载I18n国际化数据缓存.......Begin");
		CacheManager.clearOnly(GeneralConstant.I18N_KEY);
		List<I18nView> list = this.findAllView();
		Map<String, I18nView> map = new HashMap<String, I18nView>();
		if(CollectionTools.isNotBlank(list)){
			for(I18nView view : list){
				map.put(view.getCode(), view);
			}
		}
		Cache cache = new Cache();
		cache.setKey(GeneralConstant.I18N_KEY);
		cache.setValue(map);
		CacheManager.putCache(GeneralConstant.I18N_KEY, cache);
		log.info("加载I18n国际化数据缓存.......End");
	}

	@Override
	@SuppressWarnings("unchecked")
	public String getValue(String code, String language) throws ProjectException {
		Cache cache = CacheManager.getCacheInfo(GeneralConstant.I18N_KEY);
		if(null == cache){
			initCache();
			cache = CacheManager.getCacheInfo(GeneralConstant.I18N_KEY);
		}
		Map<String, I18nView> i18nMap = (Map<String, I18nView>) cache.getValue();
		return ReflectUtils.getValue(language, i18nMap.get(code)) +"";
	}

	@Override
	@SuppressWarnings("unchecked")
	public void refreshCache(String code, I18nView value) throws ProjectException {
		Cache cache = CacheManager.getCacheInfo(GeneralConstant.I18N_KEY);
		if(null == cache) {
			initCache();
			cache = CacheManager.getCacheInfo(GeneralConstant.I18N_KEY);
		} 
		Map<String, I18nView> map = (Map<String, I18nView>)cache.getValue();
		if(null == map) {
			initCache();
			cache = CacheManager.getCacheInfo(GeneralConstant.I18N_KEY);
			map = (Map<String, I18nView>) cache.getValue();
		} 
		CacheManager.clearOnly(GeneralConstant.I18N_KEY);
		map.put(code, value);
		cache.setValue(map);
		CacheManager.putCache(GeneralConstant.I18N_KEY, cache);
	}

	@SuppressWarnings("unchecked")
	@Override
	public Map<String, String> getData(String lan) throws ProjectException {
		Map<String, String> resultMap = new HashMap<String, String>();
		if(StringUtils.isBlank(lan)) lan = projectConfigration.defaultI18n;
		Cache cache = CacheManager.getCacheInfo(GeneralConstant.I18N_KEY);
		if(null == cache) return null;
		Map<String, I18nView> result =  (Map<String, I18nView>)cache.getValue();
		if(null == result) {
			initCache();
		}
		result =  (Map<String, I18nView>)cache.getValue();
		if(null == result) return resultMap;
		
		for(Entry<String, I18nView> entry : result.entrySet()) {
			resultMap.put(entry.getKey(), ReflectUtils.getValue(lan, entry.getValue()) + "");
		}
		return resultMap;
	}
}
